﻿using System;
using System.Net.Sockets;
using System.IO;

namespace ClientAPI.Network
{
    class ReceiveFile
    {
        private string _fileName;
        private string _folderLocation;

        private long _totalPackets;
        private int _packetSize;
        private long _packetNumber;

        private bool _fileIncomplete = true;
        private bool _fileReceiving = true;

        private Socket _socket;
        Messenger _messenger;

        public ReceiveFile(string fileName, Socket socket)
        {
            _fileName = fileName;
            _folderLocation = Settings.Instance.GetFolderLocation();
            _socket = socket;
            _messenger = new Messenger(_socket, "FILE RECEIVE ");
        }

        public void Receive()
        {
            _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,"+ _fileName + ",");

            FileStream fileData = new FileStream(_folderLocation + "\\" + _fileName, FileMode.Append, FileAccess.Write);
            
            int receivedBytesLen = 0;

            //System.Diagnostics.Debug.WriteLine("waiting for number packets");
            while (WaitForFileDetails()) { }

            _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,START,");

            while (_fileIncomplete)
            {
                //System.Diagnostics.Debug.WriteLine("waiting for packet details");
                while (WaitForPacketDetails()) { }
                
                _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,OK,");
                byte[] buffer = new byte[_packetSize];
                _fileReceiving = true;

                while (_fileReceiving)
                {
                    //System.Diagnostics.Debug.WriteLine("waiting to receive data");
                    receivedBytesLen = _socket.Receive(buffer);
                    //System.Diagnostics.Debug.WriteLine(receivedBytesLen);
                    
                    if (receivedBytesLen == this._packetSize)
                    {
                        _fileReceiving = false;
                        fileData.Write(buffer, 0, _packetSize); 
                        //System.Diagnostics.Debug.WriteLine("wrote data");
                    }
                    else if (receivedBytesLen != 0 && (receivedBytesLen < _packetSize || receivedBytesLen > _packetSize)) 
                    {
                        buffer = null;
                        _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,BAD,");
                    }
                }

                if (_packetNumber == _totalPackets)
                {
                    //System.Diagnostics.Debug.WriteLine("download COMPLETE");
                    _fileIncomplete = false;
                    _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,END,");
                }
                else
                {
                    //System.Diagnostics.Debug.WriteLine("download not complete");
                    _fileIncomplete = true;
                    receivedBytesLen = 0;

                    _messenger.SendMessage("$FRANK,FILE,DOWNLOAD,NEXT,");
                }              
            }
            //System.Diagnostics.Debug.WriteLine("exited loop");

            fileData.Flush();
            fileData.Close();

            _socket.Disconnect(true);
        }

        private bool WaitForFileDetails()
        {
            string[] message = _messenger.ReceiveFileInformation().Split(',');

            if (message == null)
            {
                return true;
            }
            else if (message[message.Length - 2] == "BAD")
            {
                _fileIncomplete = false;
                return false;
            }            

            this._totalPackets = Convert.ToInt64(message[message.Length-2]);

            //System.Diagnostics.Debug.WriteLine("packet numbers: " + _totalPackets);

            return false;
        }

        private bool WaitForPacketDetails()
        {
            string[] messageArray;
            string message = _messenger.ReceiveFileInformation();

            if (message == null)
            {
                return true;
            }

            messageArray = message.Split(',');

            if (messageArray[messageArray.Length - 2] == "BAD")
            {
                _fileIncomplete = false;
                return false;
            }


            _packetNumber = Convert.ToInt64(messageArray[messageArray.Length - 3]);
            _packetSize =  Convert.ToInt16(messageArray[messageArray.Length - 2]);

            System.Diagnostics.Debug.WriteLine("packet details number: " + _packetNumber + " packet size: " + _packetSize);

            return false;
        }

        private bool WaitForConformation()
        {
            string[] messageArray;
            string message = _messenger.ReceiveFileInformation();

            if (message == null)
            {
                return true;
            }

            messageArray = message.Split(',');

            if (messageArray[messageArray.Length - 2] == "OK")
                return true;
            else if (messageArray[messageArray.Length - 2] == "BAD")
            {
                _fileIncomplete = false;
                return true;
            }
            else
                return false;
        }
    }
}
